package com.tzu.ft.ui;

import com.tzu.ft.base.FTConfig;
import com.tzu.ft.base.SendParam;
import com.tzu.ft.base.TransferTools;
import com.tzu.ft.transfer.ClientFactory;
import com.tzu.ft.transfer.ClientRunning;
import com.tzu.ft.transfer.ClientUI;
import com.tzu.ft.transfer.ServerTaskFactory;
import com.tzu.ft.transfer.client.Client;
import com.tzu.ft.ui.comps.FileDragAndDropHandler;
import com.tzu.ft.ui.comps.ProcessPanel;
import com.tzu.ft.ui.comps.SettingDialog;
import com.tzu.ft.ui.utils.FTUIConst;
import com.tzu.ft.ui.utils.FTUITools;
import com.tzu.utils.StringTools;

import javax.swing.*;
import javax.swing.event.ChangeEvent;
import javax.swing.event.ChangeListener;
import java.awt.*;
import java.awt.event.ActionEvent;
import java.awt.event.ActionListener;
import java.awt.event.WindowEvent;
import java.awt.event.WindowListener;
import java.io.File;
import java.util.List;

/**
 * 文件传输UI主界面
 */
public class FTUI {

	/**
	 * Launch the application.
	 */
	public static void main(String[] args) {
		// 载入界面风格
		try {
			UIManager.setLookAndFeel(UIManager.getSystemLookAndFeelClassName());
		} catch (Exception e) {
			e.printStackTrace();
		}

		EventQueue.invokeLater(new Runnable() {
			@Override
			public void run() {
				try {
					FTUI window = new FTUI();
					window.mainFrame.setVisible(true);
				} catch (Exception e) {
					e.printStackTrace();
				}
			}
		});
	}

	private static boolean isClient = false;
	private static boolean isSsl = false;
	private static boolean isRun = false;
	public static String host;
	public static int port;
	// =============================================================
	public static int down_panel_index = 0;

	public JFrame mainFrame;

	public JPanel panelTop;

	public JScrollPane scrollPane;
	public JPanel panelDownlist;

	public FTUI ftuiMain;
	public JTextField textFiel_host;
	public JTextField textField_port;

	public JLabel label_tasknum_run;
	public JLabel label_tasknum_wait;

	public JButton btnNewButton_addfile;
	public JButton btnNewButton_setting;
	public JButton btnNewButton_path;
	public JButton btnNewButton_lsnrctl;
	public JButton btnNewButton_connect;

	public JCheckBox chckbxNewCheckBox_ssl;

	/**
	 * Create the application.
	 */
	public FTUI() {
		initialize();
		ftuiMain = this;
	}

	/**
	 * Initialize the contents of the frame.
	 */
	private void initialize() {
		mainFrame = new JFrame();
		mainFrame.getContentPane().setBackground(Color.GRAY);
		mainFrame.setTitle(FTUIConst.WINDOWS_TITLE);
		mainFrame.setResizable(false);
		mainFrame.setSize(800, 600);
		// 居中位置打开窗口
		mainFrame.setLocationRelativeTo(null);
		mainFrame.getContentPane().setLayout(null);
		addWindowClose(mainFrame);

		// 顶部面板
		panelTop = new JPanel();
		panelTop.setBounds(0, 0, 794, 170);
		panelTop.setLayout(null);
		mainFrame.getContentPane().add(panelTop);

		final JLabel lblNewLabel = new JLabel("- 未选择 -");
		lblNewLabel.setBounds(139, 10, 258, 30);
		panelTop.add(lblNewLabel);

		// 获取默认配置路径
		String defaultsavepath = FTConfig.getDefaultSavePath();
		if (StringTools.isNotBlank(defaultsavepath)) {
			lblNewLabel.setText(defaultsavepath);// 显示路径
			lblNewLabel.setToolTipText(defaultsavepath);// 鼠标提示
		}

		btnNewButton_path = new JButton("选择保存路径");
		btnNewButton_path.setIcon(new ImageIcon(FTUI.class.getResource("/com/tzu/ft/ui/icons/save_path_20.png")));
		btnNewButton_path.addActionListener(new ActionListener() {
			@Override
			public void actionPerformed(ActionEvent event) {
				JFileChooser fileChooser = new JFileChooser();
				fileChooser.setFileSelectionMode(JFileChooser.DIRECTORIES_ONLY);
				fileChooser.setDialogTitle("选择保存路径");
				int retval = fileChooser.showOpenDialog(panelTop);
				// 确认选择
				if (retval == JFileChooser.APPROVE_OPTION) {
					File path = fileChooser.getSelectedFile();
					String filePath = path.getAbsolutePath();// 这个就是你选择的文件夹的路径
					System.out.println(filePath);
					lblNewLabel.setText(filePath);// 显示路径
					lblNewLabel.setToolTipText(filePath);// 鼠标提示
					// 写入配置文件
					FTConfig.setDefaultSavePath(filePath);
				}
			}
		});
		btnNewButton_path.setBounds(407, 10, 297, 30);
		panelTop.add(btnNewButton_path);

		JLabel lblNewLabel_1 = new JLabel("默认保存路径：");
		lblNewLabel_1.setBounds(27, 10, 105, 30);
		panelTop.add(lblNewLabel_1);

		JButton btnNewButton_about = new JButton("关于");
		btnNewButton_about.addActionListener(new ActionListener() {
			@Override
			public void actionPerformed(ActionEvent e) {
				JButton button = (JButton) e.getSource();
				FTUITools.showDialogQuest(mainFrame, button.getText(), FTUIConst.ABOUT);
			}
		});
		btnNewButton_about.setBounds(718, 10, 66, 72);
		panelTop.add(btnNewButton_about);

		btnNewButton_addfile = new JButton("选择文件");
		btnNewButton_addfile.setIcon(new ImageIcon(FTUI.class.getResource("/com/tzu/ft/ui/icons/add_file_24.png")));
		btnNewButton_addfile.addActionListener(new ActionListener() {
			@Override
			public void actionPerformed(ActionEvent event) {

				if (!isRun) {
					FTUITools.showDialogError(mainFrame, "错误", "请连接服务");
					return;
				}

				JFileChooser fileChooser = new JFileChooser();
				fileChooser.setFileSelectionMode(JFileChooser.FILES_AND_DIRECTORIES);
				fileChooser.setDialogTitle("选择文件");
				// 文件多选
				fileChooser.setMultiSelectionEnabled(true);
				int retval = fileChooser.showOpenDialog(panelTop);
				// 确认选择
				if (retval == JFileChooser.APPROVE_OPTION) {
					final File[] paths = fileChooser.getSelectedFiles();
					// 发送文件
					try {
						sendFile(paths);
					} catch (Exception e) {
						e.printStackTrace();
						FTUITools.showDialogError(mainFrame, "错误", "发送失败：" + e.getMessage());
					}
				}
			}
		});

		btnNewButton_addfile.setBounds(407, 92, 297, 68);
		panelTop.add(btnNewButton_addfile);

		JLabel lblNewLabel_2 = new JLabel("连接地址：");
		lblNewLabel_2.setBounds(27, 52, 80, 30);
		panelTop.add(lblNewLabel_2);

		// ip地址输入框
		String defhost = TransferTools.getLocalIp();
		textFiel_host = new JTextField();
		textFiel_host.setText(defhost);
		textFiel_host.setBounds(108, 52, 191, 30);
		textFiel_host.setFont(FTUITools.makeFont(textFiel_host.getFont(), Font.BOLD, 16));
		panelTop.add(textFiel_host);

		// 端口号输入框
		textField_port = new JTextField(6);
		textField_port.setText(TransferTools.DEFAULT_SOCKET_PORT + "");
		textField_port.setBounds(331, 52, 66, 30);
		textField_port.setFont(FTUITools.makeFont(textField_port.getFont(), Font.BOLD, 16));
		panelTop.add(textField_port);

		btnNewButton_lsnrctl = new JButton("启动监听");
		btnNewButton_lsnrctl.addActionListener(new ActionListener() {
			@Override
			public void actionPerformed(ActionEvent e) {
				startServer();
			}
		});
		btnNewButton_lsnrctl.setBounds(407, 52, 100, 30);
		panelTop.add(btnNewButton_lsnrctl);

		btnNewButton_connect = new JButton("连接服务");
		btnNewButton_connect.addActionListener(new ActionListener() {
			@Override
			public void actionPerformed(ActionEvent e) {
				// 连接服务
				connectServer();
			}
		});
		btnNewButton_connect.setBounds(517, 52, 100, 30);
		panelTop.add(btnNewButton_connect);

		JLabel lblNewLabel_3 = new JLabel("：");
		lblNewLabel_3.setBounds(309, 52, 20, 30);
		panelTop.add(lblNewLabel_3);

		JButton btnNewButton_cancel = new JButton("取消");
		btnNewButton_cancel.addActionListener(new ActionListener() {
			@Override
			public void actionPerformed(ActionEvent e) {
				cancel();
			}
		});
		btnNewButton_cancel.setBounds(628, 52, 76, 30);
		panelTop.add(btnNewButton_cancel);

		// 任务数显示
		label_tasknum_run = new JLabel("任务：0");
		label_tasknum_run.setBounds(42, 130, 90, 30);
		panelTop.add(label_tasknum_run);
		label_tasknum_run.setVisible(false);

		// 任务数显示
		label_tasknum_wait = new JLabel("等待：0");
		label_tasknum_wait.setBounds(138, 130, 90, 30);
		panelTop.add(label_tasknum_wait);
		label_tasknum_wait.setVisible(false);

		JButton btnNewButton = new JButton("退出");
		btnNewButton.addActionListener(new ActionListener() {
			@Override
			public void actionPerformed(ActionEvent e) {
				closeSystem();
			}
		});
		btnNewButton.setBounds(718, 92, 66, 68);
		panelTop.add(btnNewButton);

		btnNewButton_setting = new JButton("设置");
		btnNewButton_setting.addActionListener(new ActionListener() {
			@Override
			public void actionPerformed(ActionEvent e) {
				// 显示设置对话框
				SettingDialog.showConfirmInfo(mainFrame);
			}
		});
		btnNewButton_setting.setBounds(331, 92, 66, 68);
		panelTop.add(btnNewButton_setting);

		chckbxNewCheckBox_ssl = new JCheckBox("启用SSL加密传输");
		chckbxNewCheckBox_ssl.setToolTipText("加密传输需要配置证书");
		chckbxNewCheckBox_ssl.setBounds(108, 93, 120, 23);
		chckbxNewCheckBox_ssl.addChangeListener(new ChangeListener() {
			@Override
			public void stateChanged(ChangeEvent e) {
				JCheckBox checkBox = (JCheckBox) e.getSource();
				openSsl(checkBox);
			}
		});
		panelTop.add(chckbxNewCheckBox_ssl);

		// 滚动条面板
		scrollPane = new JScrollPane(panelDownlist);
		scrollPane.setDoubleBuffered(true);
		scrollPane.setHorizontalScrollBarPolicy(ScrollPaneConstants.HORIZONTAL_SCROLLBAR_NEVER);
		scrollPane.setVerticalScrollBarPolicy(ScrollPaneConstants.VERTICAL_SCROLLBAR_ALWAYS);
		scrollPane.setBounds(0, 171, 794, 400);

		// 下载列表面板
		panelDownlist = new JPanel();
		panelDownlist.setDoubleBuffered(true);
		panelDownlist.setBackground(FTUIConst.COLOR_DEF);
		int rowsdef = scrollPane.getHeight() / ProcessPanel.HEIGHT_ALL;// 计算初始行数
		// 表格布局，初始化行
		panelDownlist.setLayout(new GridLayout(rowsdef, 1));
		// --添加下载列表面板
		scrollPane.setViewportView(panelDownlist);
		// 文件拖拽监听
		panelDownlist.setTransferHandler(new FileDragAndDropHandler(new FileDragAndDropHandler.DragAndDropExecute() {
			@Override
			public void execute(File[] filelist) {
				// 必须启动服务才能发送
				if (!isRun) {
					FTUITools.showDialogError(mainFrame, "错误", "请连接服务");
					return;
				}
				// 只有客户端可以拖拽文件
				if (isClient) {
					// 发送文件
					try {
						sendFile(filelist);
					} catch (Exception e) {
						e.printStackTrace();
						FTUITools.showDialogError(mainFrame, "错误", "发送失败：" + e.getMessage());
					}
				} else {
					FTUITools.showDialogError(mainFrame, "错误", "只有作为客户端时可以发送文件");
				}
			}
		}));

		mainFrame.getContentPane().add(scrollPane);

	}

	// ===================================================================================================

	/** 显示运行中的任务数 */
	public void showTaskNumRun(int num) {
		label_tasknum_run.setText("任务：" + num);
	}

	/** 显示等待执行的任务数 */
	public void showTaskNumWait(int num) {
		label_tasknum_wait.setText("等待：" + num);
	}

	/**
	 * 添加下载记录
	 */
	public void addProcessPanel(FTUI ftuiMain, String filename, String host, int port, ClientUI ui) {
		try {
			Client client = ClientFactory.getClient(host, port, ui);
			client.init(host, port, null, ui);
			client.send();
		} catch (Exception e) {
			e.printStackTrace();
		}

	}

	/**
	 * 刷新滚动条
	 */
	public void flushScoll() {
		// 进度条数量
		int count = panelDownlist.getComponentCount();
		GridLayout gridlay = (GridLayout) panelDownlist.getLayout();
//		System.out.println("面板高度：" + panelDownlist.getHeight() + "，进度条总高度： " + (count * ProcessPanel.HEIGHT_ALL)
//				+ "，布局行数：" + gridlay.getRows() + "，进度条行数：" + count);
		// 面板高度与进度条总高度差值小于1个进度条高度时
		if (scrollPane.getHeight() - count * ProcessPanel.HEIGHT_ALL < ProcessPanel.HEIGHT_ALL) {
			// 动态修改大小，额外增加一行的高度和行数
			count += 1;
			panelDownlist.setPreferredSize(new Dimension(panelDownlist.getWidth(), count * ProcessPanel.HEIGHT_ALL));
			// 修改布局增加一行
			gridlay.setRows(count);
		} else {
			// 设定高度
			panelDownlist.setPreferredSize(new Dimension(panelDownlist.getWidth(), scrollPane.getHeight() - 2));
			// 设定行数
			int rowsdef = scrollPane.getHeight() / ProcessPanel.HEIGHT_ALL;// 计算初始行数
			gridlay.setRows(rowsdef);
		}

		// 更新UI
		SwingUtilities.invokeLater(new Runnable() {
			@Override
			public void run() {
				SwingUtilities.updateComponentTreeUI(panelDownlist);
				SwingUtilities.updateComponentTreeUI(scrollPane);
			}
		});

		// 滚动到最下面
//		JScrollBar bar = scrollPane.getVerticalScrollBar();
//		bar.setValue(bar.getMaximum());
	}

	/**
	 * 退出系统
	 */
	private void closeSystem() {
		int val = JOptionPane.showConfirmDialog(mainFrame, "确定要退出程序吗？", "退出程序", JOptionPane.YES_NO_OPTION,
				JOptionPane.WARNING_MESSAGE);
		if (val == 0) {
			System.exit(0);
		}
	}

	/**
	 * 添加窗口关闭事件
	 */
	private void addWindowClose(JFrame frame) {
		// 设定关闭类型
		frame.setDefaultCloseOperation(JFrame.DO_NOTHING_ON_CLOSE);
		frame.addWindowListener(new WindowListener() {

			@Override
			public void windowOpened(WindowEvent e) {
			}

			@Override
			public void windowIconified(WindowEvent e) {

			}

			@Override
			public void windowDeiconified(WindowEvent e) {

			}

			@Override
			public void windowDeactivated(WindowEvent e) {

			}

			@Override
			public void windowClosing(WindowEvent e) {
				closeSystem();
			}

			@Override
			public void windowClosed(WindowEvent e) {
			}

			@Override
			public void windowActivated(WindowEvent e) {

			}
		});
	}

	/**
	 * 启动监听
	 */
	private void startServer() {
		// 启动服务
		String port = textField_port.getText();
		if (StringTools.isBlank(port)) {
			FTUITools.showDialogError(mainFrame, "错误", "请输入监听端口");
			return;
		}

		// 界面状态设置
		textFiel_host.setEnabled(false);
		textField_port.setEnabled(false);
		textFiel_host.setBackground(FTUIConst.COLOR_RUN);
		textField_port.setBackground(FTUIConst.COLOR_RUN);
		btnNewButton_addfile.setEnabled(false);
		btnNewButton_setting.setEnabled(false);
		btnNewButton_path.setEnabled(false);
		btnNewButton_lsnrctl.setEnabled(false);
		btnNewButton_connect.setEnabled(false);
		chckbxNewCheckBox_ssl.setEnabled(false);
		isClient = false;
		// 启动服务
		int portint = Integer.parseInt(port);
		try {
			ServerTaskFactory.init(portint, isSsl, ftuiMain);
			isRun = true;
			// 保存端口
			FTUI.port = portint;
		} catch (Exception e) {
			e.printStackTrace();
			cancel();
			FTUITools.showDialogError(mainFrame, "错误", "服务启动失败：" + e.getMessage());
		}

	}

	/**
	 * 连接服务
	 */
	private void connectServer() {

		String host = textFiel_host.getText();
		String port = textField_port.getText();
		if (StringTools.isBlank(host)) {
			FTUITools.showDialogError(mainFrame, "错误", "请输入连接地址");
			return;
		} else if (StringTools.isBlank(port)) {
			FTUITools.showDialogError(mainFrame, "错误", "请输入连接端口");
			return;
		}

		// 状态设置
		textFiel_host.setEnabled(false);
		textField_port.setEnabled(false);
		textFiel_host.setBackground(FTUIConst.COLOR_RUN);
		textField_port.setBackground(FTUIConst.COLOR_RUN);
		btnNewButton_setting.setEnabled(false);
		btnNewButton_path.setEnabled(false);
		btnNewButton_lsnrctl.setEnabled(false);
		btnNewButton_connect.setEnabled(false);
		chckbxNewCheckBox_ssl.setEnabled(false);
		//显示任务数
		label_tasknum_run.setVisible(true);
		label_tasknum_wait.setVisible(true);
		
		
		isClient = true;

		// 创建
		ClientFactory.init(isSsl);
		isRun = true;
		// 保存host和端口
		FTUI.host = host;
		FTUI.port = Integer.parseInt(port);
	}

	/**
	 * 取消
	 */
	private void cancel() {
		textFiel_host.setEnabled(true);
		textField_port.setEnabled(true);
		textFiel_host.setBackground(FTUIConst.COLOR_DEF);
		textField_port.setBackground(FTUIConst.COLOR_DEF);
		btnNewButton_addfile.setEnabled(true);
		btnNewButton_setting.setEnabled(true);
		btnNewButton_path.setEnabled(true);
		btnNewButton_lsnrctl.setEnabled(true);
		btnNewButton_connect.setEnabled(true);
		chckbxNewCheckBox_ssl.setEnabled(true);

		//显示任务数
		showTaskNumRun(0);
		showTaskNumWait(0);
		label_tasknum_run.setVisible(false);
		label_tasknum_wait.setVisible(false);

		
		isClient = false;
		isRun = false;
		FTUI.host = "";
		FTUI.port = 0;

		// 停止 所有任务，移除任务
		ClientFactory.destoryFactory();
		ServerTaskFactory.destoryServer();
		panelDownlist.removeAll();

		// 更新UI
		SwingUtilities.invokeLater(new Runnable() {
			@Override
			public void run() {
				SwingUtilities.updateComponentTreeUI(panelDownlist);
				SwingUtilities.updateComponentTreeUI(scrollPane);
			}
		});

		//显示任务数
		showTaskNumRun(0);
		showTaskNumWait(0);
		//重置面板index
		down_panel_index = 0;
	}

	/**
	 * 开启加密传输
	 */
	private void openSsl(JCheckBox jCheckBox) {
		if (jCheckBox.isSelected()) {
			// 验证证书文件
			String pubkeypath = FTConfig.getSslKeyStorePath();
			String prikeypath = FTConfig.getSslTrustStorePath();
			// 判定公私钥是否存在
			if (!new File(pubkeypath).exists() || !new File(prikeypath).exists()) {
				jCheckBox.setSelected(false);
				isSsl = false;
				FTUITools.showDialogError(mainFrame, "错误", "密钥库文件不存在，请创建");
				return;
			}
			isSsl = true;
		} else {
			isSsl = false;
		}
	}

	/**
	 * 发送文件
	 *
	 * @throws Exception
	 */
	private void sendFile(File[] filelist) throws Exception {
		for (int i = 0; i < filelist.length; i++) {

			File basefile = filelist[i];
			System.out.println(basefile.getAbsolutePath());

			// 如果是文件直接发送
			if (basefile.isFile()) {
				// 执行发送
				executeSendFile(null, basefile);
			} else if (basefile.isDirectory()) {
				// 提取根路径
//				String rootPathName = basefile.getName();
				// 提取所有文件
				List<File> takeFileList = TransferTools.takeAllFiles(basefile);
				if (takeFileList.size() > 0) {
					for (File takefile : takeFileList) {
						// 发送文件，携带路径信息
						executeSendFile(basefile, takefile);
					}
				}
			}

		}

	}

	// 处理发送
	private void executeSendFile(File basepath, File file) throws Exception {
		// 执行任务线程
		ClientFactory.addTask(new ClientRunning() {

			@Override
			public void run() {

				// 文件中间路径
				String middlepath = TransferTools.getMiddleParentPath(basepath, file);

				String tippath = middlepath + File.separator + file.getName();
				// 添加进度及处理
				this.processPanel = new ProcessPanel(down_panel_index++, file.getName(), tippath, panelDownlist);
				processPanel.showFiletypeAndSize(TransferTools.getFileExt(file.getName()),
						TransferTools.takeFileSize(file.length(), 3));
				panelDownlist.add(this.processPanel, 0);// 添加到最前面
				flushScoll();

				// 设置线程标题
				this.title = file.getName();
				// ui交互对象
				this.clientUI = new ClientUI() {

					@Override
					public SendParam getSendParam() {
						SendParam param = null;
						if (null != middlepath) {// 存在路径，说明是文件夹下的文件
							param = new SendParam(file.getName(), basepath.getName(), middlepath, file.length());
						} else {
							param = new SendParam(file.getName(), file.length());
						}
						return param;
					}

					@Override
					public File getFile() {
						return file;
					}

					@Override
					public void startFail(String msg) {
						FTUITools.showDialogError(mainFrame, "错误", msg);
					}

					@Override
					public void processStatus(String filetype, String filesize, String usdtime, double precent,
							String speed) {
						processPanel.showRun();
						processPanel.showFiletypeAndSize(filetype, filesize);
						processPanel.showSpeedAndInfo(speed, true);
						processPanel.showPrecent(precent);
						processPanel.showUsetime(usdtime);
					}

					@Override
					public void finish(int exit, String msg) {
						processPanel.delete();
					}

				};

				// 获取客户端执行
				try {
					this.client = ClientFactory.getClient(host, port, clientUI);

					// 设置进度条上的按钮执行事件
					processPanel.setProcessAction(new ProcessPanel.ProcessAction() {

						@Override
						public void stop() {
							// TODO Auto-generated method stub

						}

						@Override
						public void exit() {
							ClientFactory.destory(getInstance());
							//显示任务数
							showTaskNumRun(ClientFactory.getTaskActiveCount());
							showTaskNumWait(ClientFactory.getTaskWaitCount());
						}
					});

					// 执行发送数据
					client.send();
					//显示任务数
					showTaskNumRun(ClientFactory.getTaskActiveCount());
					showTaskNumWait(ClientFactory.getTaskWaitCount());

				} catch (Exception e) {
					e.printStackTrace();
					processPanel.showSpeedAndInfo("发送失败：" + e.getMessage(), false);
				}

			}
		});
		//显示任务数
		showTaskNumRun(ClientFactory.getTaskActiveCount());
		showTaskNumWait(ClientFactory.getTaskWaitCount());
	}
}
